package com.it.App.service.impl;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.it.App.entity.LoginUser;
import com.it.App.entity.SysUser;
import com.it.App.exception.BaseException;
import com.it.App.mapper.SysUserMapper;
import com.it.App.service.SysUserService;
import com.it.App.utils.JwtUtils;
import com.it.App.utils.RedisUtil;
import com.it.App.vo.Const;
import com.it.App.vo.Response;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @Author: CaoYouGen
 * @DateTime: 2023/11/22/12:22
 * @注释: TODO
 **/
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private JwtUtils jwtUtils;

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private ObjectMapper objectMapper;

    @Override
    public Response<?> getUserByName(String username) {
        QueryWrapper<SysUser> userQueryWrapper = new QueryWrapper<>();
        QueryWrapper<SysUser> wrapper = userQueryWrapper.eq("username", username);
        SysUser sysUser = sysUserMapper.selectOne(wrapper);
        // 是否查询到用户
        if (ObjectUtil.isNull(sysUser)) {
            return Response.error("查无此人");
        }
        return Response.ok(sysUser);
    }


    @SneakyThrows
    @Override
    public Response<?> login(SysUser sysUser) {
        // AuthenticationManager 进行用户认证
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(sysUser.getUsername(), sysUser.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        // 如果认证没有通过 给出对应的提示
        if (ObjectUtil.isNull(authenticate)) {
            throw new BaseException("用户名或密码错误！");
        }
        // 如果认证通过， 使用userId生成一个Jwt jwt存入到Response中返回
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        // 通过userId生成token
        String userId = loginUser.getSysUser().getId().toString();
        String token = jwtUtils.generateToken(userId);
        Map<Object, Object> map = MapUtil.builder().put("token", token).build();

        // 把完整的用户信息存入到redis中 统一的前缀 login  过期时间为10分钟
//        String jsonString = objectMapper.writeValueAsString(loginUser);

        redisUtil.hset(Const.Login_Key, userId, loginUser, 60 * 20);
        // 返回登录成功的结果
        return Response.ok(map);
    }

    @Override
    public Response<?> logout() {
        // 获取当前用户的认证信息
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        // 从认证信息中获取登录用户对象
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 如果登录用户为空，抛出异常，表示鉴权失败
        if (ObjectUtil.isNull(loginUser)) {
            throw new BaseException("鉴权失败！");
        }
        // 从Redis中删除用户登录信息
        String userId = loginUser.getSysUser().getId().toString();
        redisUtil.hdel(Const.Login_Key, userId);
        // 返回操作成功的响应
        return Response.ok("操作成功！");
    }
}
